import { ErrorObject } from 'ajv';
import { BrowserClient } from '@slardar/web';
import { ApiTrack } from '../core';
import { Rule, SectionTarget, RuleGroupItem } from './rule';
import { ApiTrackReporter, CustomReporter } from './reporter';

export enum ResultType {
  success = 'success',
  error = 'error',
}

export enum ValidatorType {
  JsonSchema = 'JsonSchema',
  Prefabricated = 'Prefabricated',
  Custom = 'Custom',
}

type CustomErrorObject = Record<string, unknown>;
type PresetErrorObject = Record<string, unknown>;

export type ResultInfo = {
  api_path?: string;
  log_id?: string;
  type: ResultType;
  target?: SectionTarget;
  validator_type?: ValidatorType;
  // 会在上报时拍平
  error_info?: ErrorObject | PresetErrorObject | CustomErrorObject;
  [key: string]: unknown;
};

export interface CacheConfig {
  disabled?: boolean;
  cacheCount?: number;
  timeout?: number;
}

export type DataSet = { api_path: string; log_id?: string } & Partial<Record<SectionTarget, Record<string, unknown>>>;
export interface LifecycleHook {
  onJsError?: (errorName: string, Error: unknown, extra?: Record<string, unknown>) => void;
  onReportResult?: (result?: ResultInfo) => void;
  onApiTrackReady?: (apiTrack: ApiTrack) => void;
  onCacheTimeOut?: (cacheList: DataSet[], apiTrack: ApiTrack) => void;
}

export enum ApiTrackStatus {
  UnReady = 'UnReady',
  Ready = 'Ready',
  Start = 'Start',
  Running = 'Running',
  Finished = 'Finished',
}

export type PresetSencePlugin = (apiTrack: ApiTrack, dataSet: DataSet, options?: unknown) => void;

export interface ApiTrackInitConfig extends LifecycleHook {
  env?: string;
  context?: Record<string, unknown>;
  biz_id?: string;
  reporter: ApiTrackReporter;
  rules?: Rule[]; // 接口校验规则
  cache?: CacheConfig; // 接口缓存配置，在规则未就绪时缓存请求数据，默认开启，缓存5条
  slardar?: BrowserClient; // 宿主项目slardar实例
  presets?: Record<string, PresetSencePlugin>;
  fetchRuleFn?: () => Promise<RuleGroupItem[] | undefined>; // 获取规则的异步函数
}

export interface ApiTrackConfig extends Omit<ApiTrackInitConfig, 'reporter'> {
  isOnline: boolean; // 是否线上环境，会覆盖env
  customReporter?: CustomReporter; // 宿主项目自定义上报
}
type PluginItem = (ResultInfo?: ResultInfo) => void;

export type ApiTrackPlugin<T, P> = (ctx: T, options?: P) => PluginItem;
